home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / vm / sun4.md / vmSunAsm.s < prev    next >
Encoding:
Text File  |  1992-12-19  |  50.9 KB  |  1,920 lines

  1. /*
  2.  * vmSun.s -
  3.  *
  4.  *    Subroutines to access Sun virtual memory mapping hardware.
  5.  *    All of the routines in here assume that source and destination
  6.  *    function codes are set to MMU space.
  7.  *
  8.  * Copyright (C) 1985 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #include "vmSunConst.h"
  13. #include "machAsmDefs.h"
  14.  
  15. .seg    "data"
  16. .asciz "$Header: /cdrom/src/kernel/Cvsroot/kernel/vm/sun4.md/vmSunAsm.s,v 9.8 91/10/18 01:12:33 dlong Exp $ SPRITE (Berkeley)"
  17. .align    8
  18. .seg    "text"
  19.  
  20. /*
  21.  * ----------------------------------------------------------------------------
  22.  *
  23.  * VmMachReadPTE --
  24.  *
  25.  *         Map the given hardware pmeg into the kernel's address space and 
  26.  *    return the pte at the corresponding address.  There is a reserved
  27.  *    address in the kernel that is used to map this hardware pmeg.
  28.  *
  29.  *    VmMachPTE VmMachReadPTE(pmegNum, addr)
  30.  *        int        pmegNum;    The pmeg to read the PTE for.
  31.  *        Address    addr;        The virtual address to read the PTE for.
  32.  *
  33.  * Results:
  34.  *     The value of the PTE.
  35.  *
  36.  * Side effects:
  37.  *     None.
  38.  *
  39.  * ----------------------------------------------------------------------------
  40.  */
  41. .globl    _VmMachReadPTE
  42. _VmMachReadPTE:
  43.     /* 
  44.      * Set the segment map entry.
  45.      */
  46.     sethi    %hi(_vmMachPTESegAddr), %OUT_TEMP1    /* Get access address */
  47.     ld        [%OUT_TEMP1 + %lo(_vmMachPTESegAddr)], %OUT_TEMP1
  48. #ifdef sun4c
  49.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  50. #else
  51.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  52. #endif
  53.  
  54.     /*
  55.      * Get the page map entry.
  56.      */
  57.     lda        [%o1] VMMACH_PAGE_MAP_SPACE, %RETURN_VAL_REG    /* Return it */
  58.  
  59.     retl    /* Return from leaf routine */
  60.     nop
  61.  
  62. /*
  63.  * ----------------------------------------------------------------------------
  64.  *
  65.  * VmMachWritePTE --
  66.  *
  67.  *         Map the given hardware pmeg into the kernel's address space and 
  68.  *    write the pte at the corresponding address.  There is a reserved
  69.  *    address in the kernel that is used to map this hardware pmeg.
  70.  *
  71.  *    void VmMachWritePTE(pmegNum, addr, pte)
  72.  *        int           pmegNum;    The pmeg to write the PTE for.
  73.  *        Address    addr;        The address to write the PTE for.
  74.  *        VmMachPTE    pte;        The page table entry to write.
  75.  *
  76.  * Results:
  77.  *     None.
  78.  *
  79.  * Side effects:
  80.  *     The hardware page table entry is set.
  81.  *
  82.  * ----------------------------------------------------------------------------
  83.  */
  84. .globl    _VmMachWritePTE
  85. _VmMachWritePTE:
  86.     /* 
  87.      * Set the segment map entry.
  88.      */
  89.     sethi    %hi(_vmMachPTESegAddr), %OUT_TEMP1    /* Get access address */
  90.     ld        [%OUT_TEMP1 + %lo(_vmMachPTESegAddr)], %OUT_TEMP1
  91. #ifdef sun4c
  92.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  93. #else
  94.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  95. #endif
  96.  
  97.     /*
  98.      * Set the page map entry.
  99.      */
  100.     /* place to write to */
  101.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP2
  102.     and        %o1, %OUT_TEMP2, %o1    /* Mask out low bits */
  103.     sta        %o2, [%o1] VMMACH_PAGE_MAP_SPACE
  104.  
  105.     retl    /* Return from leaf routine */
  106.     nop
  107.  
  108.  
  109. /*
  110.  * ----------------------------------------------------------------------
  111.  *
  112.  * bcopy --
  113.  *
  114.  *    Copy numBytes from *sourcePtr in to *destPtr.
  115.  *    This routine is optimized to do transfers when sourcePtr and 
  116.  *    destPtr are both double-word aligned.
  117.  *
  118.  *    void
  119.  *    bcopy(sourcePtr, destPtr, numBytes)
  120.  *        Address sourcePtr;          Where to copy from.
  121.  *        Address destPtr;            Where to copy to.
  122.  *        int numBytes;      The number of bytes to copy
  123.  *
  124.  * Results:
  125.  *    None.
  126.  *
  127.  * Side effects:
  128.  *    The area that destPtr points to is modified.
  129.  *
  130.  * ----------------------------------------------------------------------
  131.  */
  132. .globl    _bcopy
  133. _bcopy:
  134.                         /* sourcePtr in o0 */
  135.                         /* destPtr in o1 */
  136.                         /* numBytes in o2 */
  137. /*
  138.  * If the source or dest are not double-word aligned then everything must be
  139.  * done as word or byte copies.
  140.  */
  141.     or        %o0, %o1, %OUT_TEMP1
  142.     andcc    %OUT_TEMP1, 7, %g0
  143.     be        BDoubleWordCopy
  144.     nop
  145.     andcc    %OUT_TEMP1, 3, %g0
  146.     be        BWordCopy
  147.     nop
  148.     ba        BByteCopyIt
  149.     nop
  150.  
  151.     /*
  152.      * Do as many 64-byte copies as possible.
  153.      */
  154.  
  155. BDoubleWordCopy:
  156.     cmp        %o2, 64
  157.     bl         BFinishWord
  158.     nop
  159.     ldd        [%o0], %OUT_TEMP1    /* uses out_temp1 and out_temp2 */
  160.     std        %OUT_TEMP1, [%o1]
  161.     ldd        [%o0 + 8], %OUT_TEMP1
  162.     std        %OUT_TEMP1, [%o1 + 8]
  163.     ldd        [%o0 + 16], %OUT_TEMP1
  164.     std        %OUT_TEMP1, [%o1 + 16]
  165.     ldd        [%o0 + 24], %OUT_TEMP1
  166.     std        %OUT_TEMP1, [%o1 + 24]
  167.     ldd        [%o0 + 32], %OUT_TEMP1
  168.     std        %OUT_TEMP1, [%o1 + 32]
  169.     ldd        [%o0 + 40], %OUT_TEMP1
  170.     std        %OUT_TEMP1, [%o1 + 40]
  171.     ldd        [%o0 + 48], %OUT_TEMP1
  172.     std        %OUT_TEMP1, [%o1 + 48]
  173.     ldd        [%o0 + 56], %OUT_TEMP1
  174.     std        %OUT_TEMP1, [%o1 + 56]
  175.     
  176.     sub       %o2, 64, %o2
  177.     add        %o0, 64, %o0
  178.     add        %o1, 64, %o1
  179.     ba         BDoubleWordCopy
  180.     nop
  181. BWordCopy:
  182.     cmp        %o2, 64
  183.     bl        BFinishWord
  184.     nop
  185.     ld        [%o0], %OUT_TEMP1
  186.     st        %OUT_TEMP1, [%o1]
  187.     ld        [%o0 + 4], %OUT_TEMP1
  188.     st        %OUT_TEMP1, [%o1 + 4]
  189.     ld        [%o0 + 8], %OUT_TEMP1
  190.     st        %OUT_TEMP1, [%o1 + 8]
  191.     ld        [%o0 + 12], %OUT_TEMP1
  192.     st        %OUT_TEMP1, [%o1 + 12]
  193.     ld        [%o0 + 16], %OUT_TEMP1
  194.     st        %OUT_TEMP1, [%o1 + 16]
  195.     ld        [%o0 + 20], %OUT_TEMP1
  196.     st        %OUT_TEMP1, [%o1 + 20]
  197.     ld        [%o0 + 24], %OUT_TEMP1
  198.     st        %OUT_TEMP1, [%o1 + 24]
  199.     ld        [%o0 + 28], %OUT_TEMP1
  200.     st        %OUT_TEMP1, [%o1 + 28]
  201.     ld        [%o0 + 32], %OUT_TEMP1
  202.     st        %OUT_TEMP1, [%o1 + 32]
  203.     ld        [%o0 + 36], %OUT_TEMP1
  204.     st        %OUT_TEMP1, [%o1 + 36]
  205.     ld        [%o0 + 40], %OUT_TEMP1
  206.     st        %OUT_TEMP1, [%o1 + 40]
  207.     ld        [%o0 + 44], %OUT_TEMP1
  208.     st        %OUT_TEMP1, [%o1 + 44]
  209.     ld        [%o0 + 48], %OUT_TEMP1
  210.     st        %OUT_TEMP1, [%o1 + 48]
  211.     ld        [%o0 + 52], %OUT_TEMP1
  212.     st        %OUT_TEMP1, [%o1 + 52]
  213.     ld        [%o0 + 56], %OUT_TEMP1
  214.     st        %OUT_TEMP1, [%o1 + 56]
  215.     ld        [%o0 + 60], %OUT_TEMP1
  216.     st        %OUT_TEMP1, [%o1 + 60]
  217.     
  218.     sub       %o2, 64, %o2
  219.     add        %o0, 64, %o0
  220.     add        %o1, 64, %o1
  221.     ba         BWordCopy
  222.     nop
  223.  
  224.     /*
  225.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  226.      * quickly by dispatching into the middle of a sequence of move
  227.      * instructions, but I don't yet.
  228.      */
  229.  
  230. BFinishWord:
  231.     cmp        %o2, 4
  232.     bl        BByteCopyIt
  233.     nop
  234.     ld        [%o0], %OUT_TEMP1
  235.     st        %OUT_TEMP1, [%o1]
  236.     sub        %o2, 4, %o2
  237.     add        %o0, 4, %o0
  238.     add        %o1, 4, %o1
  239.     ba        BFinishWord
  240.     nop
  241.     
  242.     /*
  243.      * Do one byte copies until done.
  244.      */
  245. BByteCopyIt:
  246.     tst        %o2
  247.     ble         BDoneCopying
  248.     nop
  249.     ldub    [%o0], %OUT_TEMP1
  250.     stb        %OUT_TEMP1, [%o1]
  251.     sub        %o2, 1, %o2
  252.     add        %o0, 1, %o0
  253.     add        %o1, 1, %o1
  254.     ba         BByteCopyIt
  255.     nop
  256.  
  257.     /* 
  258.      * Return.
  259.      */
  260.  
  261. BDoneCopying: 
  262.     retl        /* return from leaf routine */
  263.     nop
  264.  
  265. /*
  266.  * ----------------------------------------------------------------------------
  267.  *
  268.  * VmMachGetPageMap --
  269.  *
  270.  *         Return the page map entry for the given virtual address.
  271.  *    It is assumed that the user context register is set to the context
  272.  *    for which the page map entry is to retrieved.
  273.  *
  274.  *    int Vm_GetPageMap(virtualAddress)
  275.  *        Address virtualAddress;
  276.  *
  277.  * Results:
  278.  *     The contents of the hardware page map entry.
  279.  *
  280.  * Side effects:
  281.  *     None.
  282.  *
  283.  * ----------------------------------------------------------------------------
  284.  */
  285. .globl    _VmMachGetPageMap
  286. _VmMachGetPageMap:
  287.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP1
  288.     and        %o0, %OUT_TEMP1, %o0    /* relevant bits from addr */
  289.     lda        [%o0] VMMACH_PAGE_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  290.  
  291.     retl                    /* Return */
  292.     nop
  293.  
  294. /*
  295.  * ----------------------------------------------------------------------------
  296.  *
  297.  * VmMachGetSegMap --
  298.  *
  299.  *         Return the segment map entry for the given virtual address.
  300.  *    It is assumed that the user context register is set to the context
  301.  *    for which the segment map entry is to retrieved.
  302.  *
  303.  *    int VmMachGetSegMap(virtualAddress)
  304.  *        Address virtualAddress;
  305.  *
  306.  * Results:
  307.  *     The contents of the segment map entry.
  308.  *
  309.  * Side effects:
  310.  *     None.
  311.  *
  312.  * ----------------------------------------------------------------------------
  313.  */
  314. .globl    _VmMachGetSegMap
  315. _VmMachGetSegMap:
  316.     set        VMMACH_SEG_MAP_MASK, %OUT_TEMP1
  317.     and        %o0, %OUT_TEMP1, %o0    /* Get relevant bits. */
  318. #ifdef sun4c
  319.     lduba    [%o0] VMMACH_SEG_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  320. #else
  321.     lduha    [%o0] VMMACH_SEG_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  322.     /*
  323.      * bug fix for 4/110 -- mask out weird bits
  324.      */
  325.     sethi    %hi(_vmPmegMask), %OUT_TEMP1
  326.     ld        [%OUT_TEMP1 + %lo(_vmPmegMask)], %OUT_TEMP1
  327.     and        %RETURN_VAL_REG, %OUT_TEMP1, %RETURN_VAL_REG
  328. #endif
  329.     retl        /* Return from leaf routine */
  330.     nop
  331.  
  332. /*
  333.  * ----------------------------------------------------------------------------
  334.  *
  335.  * VmMachSetPageMap --
  336.  *
  337.  *         Set the page map entry for the given virtual address to the pte valud 
  338.  *      given in pte.  It is assumed that the user context register is 
  339.  *    set to the context for which the page map entry is to be set.
  340.  *
  341.  *    void VmMachSetPageMap(virtualAddress, pte)
  342.  *        Address     virtualAddress;
  343.  *        VmMachPTE    pte;
  344.  *
  345.  * Results:
  346.  *     None.
  347.  *
  348.  * Side effects:
  349.  *     The hardware page map entry is set.
  350.  *
  351.  * ----------------------------------------------------------------------------
  352.  */
  353. .globl    _VmMachSetPageMap
  354. _VmMachSetPageMap:
  355.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP1
  356.     and        %o0, %OUT_TEMP1, %o0    /* Mask out low bits */
  357.     sta        %o1, [%o0] VMMACH_PAGE_MAP_SPACE    /* write map entry */
  358.  
  359.     retl        /* Return from leaf routine */
  360.     nop
  361.  
  362. /*
  363.  * ----------------------------------------------------------------------------
  364.  *
  365.  * VmMachPMEGZero --
  366.  *
  367.  *         Set all of the page table entries in the pmeg to 0.  There is a special
  368.  *    address in the kernel's address space (vmMachPMEGSegAddr) that is used
  369.  *    to map the pmeg in so that it can be zeroed.
  370.  *
  371.  *    void VmMachPMEGZero(pmeg)
  372.  *        int pmeg;
  373.  *
  374.  * Results:
  375.  *     None.
  376.  *
  377.  * Side effects:
  378.  *     The given pmeg is zeroed.
  379.  *
  380.  * ----------------------------------------------------------------------------
  381.  */
  382.  
  383. .globl    _VmMachPMEGZero
  384. _VmMachPMEGZero:
  385.     /* Write segment map entry */
  386.     sethi    %hi(_vmMachPMEGSegAddr), %OUT_TEMP1
  387.     ld        [%OUT_TEMP1 + %lo(_vmMachPMEGSegAddr)], %OUT_TEMP1
  388. #ifdef sun4c
  389.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE
  390. #else
  391.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE
  392. #endif
  393.  
  394.     /*
  395.      * Now zero out all page table entries.  %OUT_TEMP1 is starting address
  396.      * and %OUT_TEMP2 is ending address.
  397.      */
  398.     
  399.     set        VMMACH_SEG_SIZE, %OUT_TEMP2
  400.     add        %OUT_TEMP1, %OUT_TEMP2, %OUT_TEMP2
  401.  
  402. KeepZeroing:
  403.     sta        %g0, [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE
  404.     set        VMMACH_PAGE_SIZE_INT, %g1
  405.     add        %OUT_TEMP1, %g1, %OUT_TEMP1
  406.     cmp        %OUT_TEMP1, %OUT_TEMP2
  407.     bcs        KeepZeroing
  408.     nop
  409.  
  410.     retl    /* Return from leaf routine */
  411.     nop
  412.  
  413. /*
  414.  * ----------------------------------------------------------------------------
  415.  *
  416.  * VmMachReadAndZeroPMEG --
  417.  *
  418.  *    Read out all page table entries in the given pmeg and then set each to
  419.  *    zero. There is a special address in the kernel's address space 
  420.  *    (vmMachPMEGSegAddr) that is used to access the PMEG.
  421.  *
  422.  *    void VmMachPMEGZero(pmeg, pteArray)
  423.  *        int     pmeg;
  424.  *        VmMachPTE    pteArray[VMMACH_NUM_PAGES_PER_SEG];
  425.  *
  426.  * Results:
  427.  *      None.
  428.  *
  429.  * Side effects:
  430.  *     The given pmeg is zeroed and *pteArray is filled in with the contents
  431.  *    of the PMEG before it is zeroed.
  432.  *
  433.  * ----------------------------------------------------------------------------
  434.  */
  435.  
  436. .globl    _VmMachReadAndZeroPMEG
  437. _VmMachReadAndZeroPMEG:
  438.     /*
  439.      * %OUT_TEMP1 is address.  %OUT_TEMP2 is a counter.
  440.      */
  441.     sethi    %hi(_vmMachPMEGSegAddr), %OUT_TEMP1
  442.     ld        [%OUT_TEMP1 + %lo(_vmMachPMEGSegAddr)], %OUT_TEMP1
  443. #ifdef sun4c
  444.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write PMEG */
  445. #else
  446.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write PMEG */
  447. #endif
  448.  
  449.     set        VMMACH_NUM_PAGES_PER_SEG_INT, %OUT_TEMP2
  450. KeepZeroing2:
  451.     lda        [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE, %o0    /* Read out the pte */
  452.     st        %o0, [%o1]                /* pte into array */
  453.     add        %o1, 4, %o1            /* increment array */
  454.     sta        %g0, [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE    /* Clear out the pte. */
  455.     set        VMMACH_PAGE_SIZE_INT, %g1
  456.     add        %OUT_TEMP1, %g1, %OUT_TEMP1    /* next addr */
  457.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2
  458.     bg        KeepZeroing2
  459.     nop
  460.  
  461.     retl    /* Return from leaf routine */            
  462.     nop
  463.  
  464.  
  465. /*
  466.  * ----------------------------------------------------------------------------
  467.  *
  468.  * VmMachSetSegMap --
  469.  *
  470.  *         Set the segment map entry for the given virtual address to the given 
  471.  *    value.  It is assumed that the user context register is set to the 
  472.  *    context for which the segment map entry is to be set.
  473.  *
  474.  *    void VmMachSetSegMap(virtualAddress, value)
  475.  *        Address    virtualAddress;
  476.  *        int        value;
  477.  *
  478.  * Results:
  479.  *     None.
  480.  *
  481.  * Side effects:
  482.  *     Hardware segment map entry for the current user context is set.
  483.  *
  484.  * ----------------------------------------------------------------------------
  485.  */
  486. .globl    _VmMachSetSegMap
  487. _VmMachSetSegMap:
  488. #ifdef sun4c
  489.     stba    %o1, [%o0] VMMACH_SEG_MAP_SPACE        /* write value to map */
  490. #else
  491.     stha    %o1, [%o0] VMMACH_SEG_MAP_SPACE        /* write value to map */
  492. #endif
  493.  
  494.     retl    /* return from leaf routine */
  495.     nop
  496.  
  497. /*
  498.  * ----------------------------------------------------------------------------
  499.  *
  500.  * VmMachCopyUserSegMap --
  501.  *
  502.  *         Copy the software segment map entries into the hardware segment entries.
  503.  *    All segment table entries for user address space up to the bottom of
  504.  *    the hole in the virtual address space are copied.
  505.  *    It is assumed that the user context register is 
  506.  *    set to the context for which the segment map entries are to be set.
  507.  *    
  508.  *    void VmMachCopyUserSegMap(tablePtr)
  509.  *        unsigned short *tablePtr;
  510.  *
  511.  * Results:
  512.  *     None.
  513.  *
  514.  * Side effects:
  515.  *     Hardware segment map entries for the current user context are set.
  516.  *
  517.  * ----------------------------------------------------------------------------
  518.  */
  519. .globl _VmMachCopyUserSegMap
  520. _VmMachCopyUserSegMap:
  521.     /*
  522.      * Due to the hole in the address space, I must make sure that no
  523.      * segment for an address in the hole gets anything written to it, since
  524.      * this would overwrite the pmeg mapping for a valid address's segment.
  525.      */
  526.  
  527.     /* Start prologue */
  528.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  529.     save    %sp, %OUT_TEMP1, %sp
  530.     /* end prologue */
  531.                         /* segTableAddr in %i0 */
  532.  
  533.     set        VMMACH_BOTTOM_OF_HOLE, %OUT_TEMP2    /* contains end addr */
  534.     srl        %OUT_TEMP2, VMMACH_SEG_SHIFT, %OUT_TEMP1    /* num segs */
  535.  
  536.     /* panic if not divisable by 8, since we do 8 at a time in loop */
  537.     andcc    %OUT_TEMP1, 7, %g0
  538.     be        StartCopySetup
  539.     nop
  540.     /*    Call panic - what args? */
  541.     clr        %o0
  542.     call    _panic, 1
  543.     nop
  544.  
  545. StartCopySetup:
  546.     /* preload offsets - each another seg size away */
  547.     set        VMMACH_SEG_SIZE, %i1
  548.     add        %i1, %i1, %i2
  549.     add        %i1, %i2, %i3
  550.     add        %i1, %i3, %i4
  551.     add        %i1, %i4, %i5
  552.     add        %i1, %i5, %o1
  553.     add        %i1, %o1, %o2
  554.     clr        %o0
  555. CopyLoop:
  556. #ifdef sun4c
  557.     lduh    [%i0], %OUT_TEMP1
  558.     stba    %OUT_TEMP1, [%o0] VMMACH_SEG_MAP_SPACE
  559.     lduh    [%i0 + 2], %OUT_TEMP1
  560.     stba    %OUT_TEMP1, [%o0 + %i1] VMMACH_SEG_MAP_SPACE
  561.     lduh    [%i0 + 4], %OUT_TEMP1
  562.     stba    %OUT_TEMP1, [%o0 + %i2] VMMACH_SEG_MAP_SPACE
  563.     lduh    [%i0 + 6], %OUT_TEMP1
  564.     stba    %OUT_TEMP1, [%o0 + %i3] VMMACH_SEG_MAP_SPACE
  565.     lduh    [%i0 + 8], %OUT_TEMP1
  566.     stba    %OUT_TEMP1, [%o0 + %i4] VMMACH_SEG_MAP_SPACE
  567.     lduh    [%i0 + 10], %OUT_TEMP1
  568.     stba    %OUT_TEMP1, [%o0 + %i5] VMMACH_SEG_MAP_SPACE
  569.     lduh    [%i0 + 12], %OUT_TEMP1
  570.     stba    %OUT_TEMP1, [%o0 + %o1] VMMACH_SEG_MAP_SPACE
  571.     lduh    [%i0 + 14], %OUT_TEMP1
  572.     stba    %OUT_TEMP1, [%o0 + %o2] VMMACH_SEG_MAP_SPACE
  573. #else
  574.     lduh    [%i0], %OUT_TEMP1
  575.     stha    %OUT_TEMP1, [%o0] VMMACH_SEG_MAP_SPACE
  576.     lduh    [%i0 + 2], %OUT_TEMP1
  577.     stha    %OUT_TEMP1, [%o0 + %i1] VMMACH_SEG_MAP_SPACE
  578.     lduh    [%i0 + 4], %OUT_TEMP1
  579.     stha    %OUT_TEMP1, [%o0 + %i2] VMMACH_SEG_MAP_SPACE
  580.     lduh    [%i0 + 6], %OUT_TEMP1
  581.     stha    %OUT_TEMP1, [%o0 + %i3] VMMACH_SEG_MAP_SPACE
  582.     lduh    [%i0 + 8], %OUT_TEMP1
  583.     stha    %OUT_TEMP1, [%o0 + %i4] VMMACH_SEG_MAP_SPACE
  584.     lduh    [%i0 + 10], %OUT_TEMP1
  585.     stha    %OUT_TEMP1, [%o0 + %i5] VMMACH_SEG_MAP_SPACE
  586.     lduh    [%i0 + 12], %OUT_TEMP1
  587.     stha    %OUT_TEMP1, [%o0 + %o1] VMMACH_SEG_MAP_SPACE
  588.     lduh    [%i0 + 14], %OUT_TEMP1
  589.     stha    %OUT_TEMP1, [%o0 + %o2] VMMACH_SEG_MAP_SPACE
  590. #endif /* sun4c */
  591.  
  592.     set        (8 * VMMACH_SEG_SIZE), %OUT_TEMP1
  593.     add        %o0, %OUT_TEMP1, %o0
  594.     cmp        %o0, %OUT_TEMP2        /* compare against end addr */
  595.     blu        CopyLoop
  596.     add        %i0, 16, %i0        /* delay slot */
  597.  
  598.     ret
  599.     restore
  600.  
  601. /*
  602.  * ----------------------------------------------------------------------------
  603.  *
  604.  * VmMachGetContextReg --
  605.  *
  606.  *         Return the value of the context register.
  607.  *
  608.  *    int VmMachGetContextReg()
  609.  *
  610.  * Results:
  611.  *     The value of context register.
  612.  *
  613.  * Side effects:
  614.  *     None.
  615.  *
  616.  * ----------------------------------------------------------------------------
  617.  */
  618.  
  619. .globl    _VmMachGetContextReg
  620. _VmMachGetContextReg:
  621.                     /* Move context reg into result reg  */
  622.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  623.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  624.  
  625.     retl        /* Return from leaf routine */
  626.     nop
  627.  
  628. /*
  629.  * ----------------------------------------------------------------------------
  630.  *
  631.  * VmMachSetContextReg --
  632.  *
  633.  *         Set the user and kernel context registers to the given value.
  634.  *
  635.  *    void VmMachSetContext(value)
  636.  *        int value;        Value to set register to
  637.  *
  638.  * Results:
  639.  *     None.
  640.  *
  641.  * Side effects:
  642.  *     None.
  643.  *
  644.  * ----------------------------------------------------------------------------
  645.  */
  646. .globl    _VmMachSetContextReg
  647. _VmMachSetContextReg:
  648.  
  649.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  650.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  651.  
  652.     retl        /* Return from leaf routine */
  653.     nop
  654.  
  655. /*
  656.  * ----------------------------------------------------------------------------
  657.  *
  658.  * VmMachGetUserContext --
  659.  *
  660.  *         Return the value of the user context register.
  661.  *
  662.  *    int VmMachGetUserContext()
  663.  *
  664.  * Results:
  665.  *     The value of user context register.
  666.  *
  667.  * Side effects:
  668.  *     None.
  669.  *
  670.  * ----------------------------------------------------------------------------
  671.  */
  672. .globl    _VmMachGetUserContext
  673. _VmMachGetUserContext:
  674.     /* There is no separate user context register on the sun4. */
  675.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  676.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  677.     
  678.     retl            /* Return from leaf routine */
  679.     nop
  680.  
  681. /*
  682.  * ----------------------------------------------------------------------------
  683.  *
  684.  * VmMachGetKernelContext --
  685.  *
  686.  *         Return the value of the kernel context register.
  687.  *
  688.  *    int VmMachGetKernelContext()
  689.  *
  690.  * Results:
  691.  *     The value of kernel context register.
  692.  *
  693.  * Side effects:
  694.  *     None.
  695.  *
  696.  * ----------------------------------------------------------------------------
  697.  */
  698. .globl    _VmMachGetKernelContext
  699. _VmMachGetKernelContext:
  700.     /* There is no separate kernel context register on the sun4. */
  701.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  702.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  703.     retl
  704.     nop
  705.  
  706. /*
  707.  * ----------------------------------------------------------------------------
  708.  *
  709.  * VmMachSetUserContext --
  710.  *
  711.  *         Set the user context register to the given value.
  712.  *
  713.  *    void VmMachSetUserContext(value)
  714.  *        int value;         Value to set register to
  715.  *
  716.  * Results:
  717.  *     None.
  718.  *
  719.  * Side effects:
  720.  *     None.
  721.  *
  722.  * ----------------------------------------------------------------------------
  723.  */
  724.  
  725. .globl    _VmMachSetUserContext
  726. _VmMachSetUserContext:
  727.     /* There is no separate user context register on the sun4. */
  728.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  729.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  730.     retl            /* Return from leaf routine */
  731.     nop
  732.  
  733. /*
  734.  * ----------------------------------------------------------------------------
  735.  *
  736.  * VmMachSetKernelContext --
  737.  *
  738.  *         Set the kernel context register to the given value.
  739.  *
  740.  *    void VmMachSetKernelContext(value)
  741.  *        int value;        Value to set register to
  742.  *
  743.  * Results:
  744.  *     None.
  745.  *
  746.  * Side effects:
  747.  *     The supervisor context is set.
  748.  *
  749.  * ----------------------------------------------------------------------------
  750.  */
  751.  
  752. .globl    _VmMachSetKernelContext
  753. _VmMachSetKernelContext:
  754.     /* There is no separate kernel context register on the sun4. */
  755.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  756.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  757.     retl            /* Return from leaf routine */
  758.     nop
  759.  
  760. /*
  761.  * ----------------------------------------------------------------------------
  762.  *
  763.  * VmMachInitSystemEnableReg --
  764.  *
  765.  *         Set the system enable register to turn on caching, etc.
  766.  *
  767.  *    void VmMachInitSystemEnableReg()
  768.  *
  769.  * Results:
  770.  *     None.
  771.  *
  772.  * Side effects:
  773.  *     Caching will be turned on, if it wasn't already.
  774.  *
  775.  * ----------------------------------------------------------------------------
  776.  */
  777. .globl    _VmMachInitSystemEnableReg
  778. _VmMachInitSystemEnableReg:
  779.     set        VMMACH_SYSTEM_ENABLE_REG, %OUT_TEMP1
  780.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %o0
  781. #ifdef sun4c
  782.     or        %o0, VMMACH_ENABLE_CACHE_BIT | VMMACH_ENABLE_DVMA_BIT, %o0
  783. #else
  784.     or          %o0, VMMACH_ENABLE_CACHE_BIT, %o0
  785. #endif
  786.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  787.     retl            /* Return from leaf routine */
  788.     nop
  789.  
  790. #ifndef sun4c
  791. /* Not used in sun4c */
  792. /*
  793.  * ----------------------------------------------------------------------------
  794.  *
  795.  * VmMachInitAddrErrorControlReg --
  796.  *
  797.  *         Set the addr error control register to enable asynchronous memory
  798.  *    error reporting.
  799.  *
  800.  *    void VmMachInitAddrErrorControlReg()
  801.  *
  802.  * Results:
  803.  *     None.
  804.  *
  805.  * Side effects:
  806.  *     Asynchronous memory errors may now be reported.
  807.  *
  808.  * ----------------------------------------------------------------------------
  809.  */
  810. .globl    _VmMachInitAddrErrorControlReg
  811. _VmMachInitAddrErrorControlReg:
  812.     set        VMMACH_ADDR_CONTROL_REG, %OUT_TEMP1
  813.     ld        [%OUT_TEMP1], %OUT_TEMP2
  814.     or        %OUT_TEMP2, VMMACH_ENABLE_MEM_ERROR_BIT, %OUT_TEMP2
  815.     st        %OUT_TEMP2, [%OUT_TEMP1]
  816.     retl
  817.     nop
  818. #endif
  819.  
  820.  
  821.  
  822. /*
  823.  * ----------------------------------------------------------------------------
  824.  *
  825.  * VmMachClearCacheTags --
  826.  *
  827.  *         Clear all tags in the cache.
  828.  *
  829.  *    void VmMachClearCacheTags()
  830.  *
  831.  * Results:
  832.  *     None.
  833.  *
  834.  * Side effects:
  835.  *     None.
  836.  *
  837.  * ----------------------------------------------------------------------------
  838.  */
  839. .globl    _VmMachClearCacheTags
  840. _VmMachClearCacheTags:
  841.     set        VMMACH_CACHE_TAGS_ADDR, %OUT_TEMP1
  842.     set        VMMACH_NUM_CACHE_TAGS, %OUT_TEMP2
  843. ClearTags:
  844.     sta        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE        /* clear tag */
  845.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2            /* dec cntr */
  846.     bne        ClearTags
  847.     add        %OUT_TEMP1, VMMACH_CACHE_TAG_INCR, %OUT_TEMP1    /* delay slot */
  848.  
  849.     retl
  850.     nop
  851.  
  852. /*
  853.  * ----------------------------------------------------------------------------
  854.  *
  855.  * VmMachFlushCurrentContext --
  856.  *
  857.  *         Flush the current context from the cache.
  858.  *
  859.  *    void VmMachFlushCurrentContext()
  860.  *
  861.  * Results:
  862.  *     None.
  863.  *
  864.  * Side effects:
  865.  *     All data cached from the current context is flushed from the cache.
  866.  *
  867.  * ----------------------------------------------------------------------------
  868.  */
  869. .globl    _VmMachFlushCurrentContext
  870. _VmMachFlushCurrentContext:
  871.     /* Start prologue */
  872.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  873.     save    %sp, %OUT_TEMP1, %sp
  874.     /* end prologue */
  875.     sethi    %hi(_vmMachHasHwFlush), %OUT_TEMP1
  876.     ld        [%OUT_TEMP1 + %lo(_vmMachHasHwFlush)], %OUT_TEMP1
  877.     tst        %OUT_TEMP1
  878.     be        SoftFlushCurrentContext
  879.     nop
  880.     /*
  881.      * 4/75 has a hardware page at a time flush that can clear a
  882.      * context a page at a time.
  883.      */
  884. #ifdef sun4c
  885.     sethi    %hi(_vmCacheSize), %l0
  886.     ld        [%l0 + %lo(_vmCacheSize)], %l0
  887. #else
  888.     set        VMMACH_CACHE_SIZE, %l0
  889. #endif
  890.     set        VMMACH_PAGE_SIZE_INT, %l1
  891. HwFlushingContext:
  892.     subcc      %l0, %l1, %l0
  893.     bg        HwFlushingContext
  894.     sta        %g0, [%l0] VMMACH_HWFLUSH_CONTEXT_SPACE
  895.  
  896.     ret
  897.     restore
  898.  
  899. SoftFlushCurrentContext:
  900.     /*
  901.      * Spread the stores evenly through 16 chunks of the cache.  This helps
  902.      * to avoid back-to-back writebacks.
  903.      */
  904. #ifdef sun4c
  905.     sethi    %hi(_vmCacheSize), %l0
  906.     ld        [%l0 + %lo(_vmCacheSize)], %l0
  907.     srl        %l0, 4, %l0
  908. #else
  909.     set        (VMMACH_CACHE_SIZE / 16), %l0
  910. #endif
  911.  
  912.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  913. #ifdef sun4c
  914.     sethi    %hi(_vmCacheLineSize), %i5
  915.     ld        [%i5 + %lo(_vmCacheLineSize)], %i5
  916. #else
  917.     set        VMMACH_CACHE_LINE_SIZE, %i5
  918. #endif
  919.     sub        %l0, %i5, %i0
  920.  
  921.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  922.     add        %l0, %l0, %l1
  923.     add        %l1, %l0, %l2
  924.     add        %l2, %l0, %l3
  925.     add        %l3, %l0, %l4
  926.     add        %l4, %l0, %l5
  927.     add        %l5, %l0, %l6
  928.     add        %l6, %l0, %l7
  929.  
  930.     add        %l7, %l0, %o0
  931.     add        %o0, %l0, %o1
  932.     add        %o1, %l0, %o2
  933.     add        %o2, %l0, %o3
  934.     add        %o3, %l0, %o4
  935.     add        %o4, %l0, %o5
  936.     add        %o5, %l0, %i4
  937.  
  938.     sta        %g0, [%i0] VMMACH_FLUSH_CONTEXT_SPACE
  939. FlushingContext:
  940.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_CONTEXT_SPACE
  941.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_CONTEXT_SPACE
  942.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_CONTEXT_SPACE
  943.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_CONTEXT_SPACE
  944.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_CONTEXT_SPACE
  945.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_CONTEXT_SPACE
  946.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_CONTEXT_SPACE
  947.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_CONTEXT_SPACE
  948.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_CONTEXT_SPACE
  949.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_CONTEXT_SPACE
  950.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_CONTEXT_SPACE
  951.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_CONTEXT_SPACE
  952.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_CONTEXT_SPACE
  953.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_CONTEXT_SPACE
  954.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_CONTEXT_SPACE
  955.  
  956.     subcc    %i0, %i5, %i0                /* decrement loop */
  957.     bge,a    FlushingContext
  958.                             /* delay slot */
  959.     sta        %g0, [%i0] VMMACH_FLUSH_CONTEXT_SPACE
  960.  
  961.     ret
  962.     restore
  963.  
  964. /*
  965.  * ----------------------------------------------------------------------------
  966.  *
  967.  * VmMachFlushSegment --
  968.  *
  969.  *         Flush a segment from the cache.
  970.  *
  971.  *    void VmMachFlushSegment(segVirtAddr)
  972.  *    Address    segVirtAddr;    (Address of segment)
  973.  *
  974.  * Results:
  975.  *     None.
  976.  *
  977.  * Side effects:
  978.  *     All data cached from the segment is flushed from the cache.
  979.  *
  980.  * ----------------------------------------------------------------------------
  981.  */
  982. .globl    _VmMachFlushSegment
  983. _VmMachFlushSegment:
  984.     /* Start prologue */
  985.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  986.     save    %sp, %OUT_TEMP1, %sp
  987.     /* end prologue */
  988.  
  989.     set        VMMACH_SEG_MAP_MASK, %o0
  990.     and        %i0, %o0, %i0                /* beginning of seg */
  991.     
  992.     sethi    %hi(_vmMachHasHwFlush), %OUT_TEMP1
  993.     ld        [%OUT_TEMP1 + %lo(_vmMachHasHwFlush)], %OUT_TEMP1
  994.     tst        %OUT_TEMP1
  995.     be        SoftFlushSegment
  996.     nop
  997.     /*
  998.      * 4/75 has a hardware page at a time flush that can clear a
  999.      * segment a page at a time.
  1000.      */
  1001. #ifdef sun4c
  1002.     sethi    %hi(_vmCacheSize), %l0
  1003.     ld        [%l0 + %lo(_vmCacheSize)], %l0
  1004. #else
  1005.     set        VMMACH_CACHE_SIZE, %l0
  1006. #endif
  1007.     set        VMMACH_PAGE_SIZE_INT, %l1
  1008. HwFlushingSegment:
  1009.     subcc      %l0, %l1, %l0
  1010.     bg        HwFlushingSegment
  1011.     sta        %g0, [%i0 + %l0] VMMACH_HWFLUSH_SEG_SPACE
  1012.  
  1013.     ret
  1014.     restore
  1015.  
  1016. SoftFlushSegment:
  1017.  
  1018.     set        VMMACH_NUM_CACHE_LINES / 16, %i1    /* num loops */
  1019.  
  1020.     /*
  1021.      * Spread the stores evenly through 16 chunks of the cache.  This helps
  1022.      * to avoid back-to-back writebacks.
  1023.      */
  1024. #ifdef sun4c
  1025.     sethi    %hi(_vmCacheSize), %l0
  1026.     ld        [%l0 + %lo(_vmCacheSize)], %l0
  1027.     srl        %l0, 4, %l0
  1028. #else
  1029.     set        (VMMACH_CACHE_SIZE / 16), %l0
  1030. #endif
  1031.  
  1032.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  1033.     add        %i0, %l0, %i0
  1034. #ifdef sun4c
  1035.     sethi    %hi(_vmCacheLineSize), %i5
  1036.     ld        [%i5 + %lo(_vmCacheLineSize)], %i5
  1037. #else
  1038.     set        VMMACH_CACHE_LINE_SIZE, %i5
  1039. #endif
  1040.     sub        %i0, %i5, %i0
  1041.  
  1042.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  1043.     add        %l0, %l0, %l1
  1044.     add        %l1, %l0, %l2
  1045.     add        %l2, %l0, %l3
  1046.     add        %l3, %l0, %l4
  1047.     add        %l4, %l0, %l5
  1048.     add        %l5, %l0, %l6
  1049.     add        %l6, %l0, %l7
  1050.  
  1051.     add        %l7, %l0, %o0
  1052.     add        %o0, %l0, %o1
  1053.     add        %o1, %l0, %o2
  1054.     add        %o2, %l0, %o3
  1055.     add        %o3, %l0, %o4
  1056.     add        %o4, %l0, %o5
  1057.     add        %o5, %l0, %i4
  1058.  
  1059. FlushingSegment:
  1060.     sta        %g0, [%i0] VMMACH_FLUSH_SEG_SPACE
  1061.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_SEG_SPACE
  1062.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_SEG_SPACE
  1063.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_SEG_SPACE
  1064.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_SEG_SPACE
  1065.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_SEG_SPACE
  1066.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_SEG_SPACE
  1067.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_SEG_SPACE
  1068.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_SEG_SPACE
  1069.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_SEG_SPACE
  1070.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_SEG_SPACE
  1071.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_SEG_SPACE
  1072.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_SEG_SPACE
  1073.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_SEG_SPACE
  1074.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_SEG_SPACE
  1075.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_SEG_SPACE
  1076.  
  1077.     subcc    %i1, 1, %i1                /* decrement loop */
  1078.     bne        FlushingSegment
  1079.                             /* delay slot */
  1080.     sub        %i0, %i5, %i0
  1081.  
  1082.     ret
  1083.     restore
  1084.  
  1085. /*
  1086.  * ----------------------------------------------------------------------------
  1087.  *
  1088.  * VmMach_FlushByteRange --
  1089.  *
  1090.  *         Flush a range of bytes from the cache.
  1091.  *
  1092.  *    void VmMachFlushByteRange(virtAddr, numBytes)
  1093.  *    Address    virtAddr;    (Address of page)
  1094.  *    int    numBytes;    (Number of bytes to flush)
  1095.  *
  1096.  * Results:
  1097.  *     None.
  1098.  *
  1099.  * Side effects:
  1100.  *     All data cached in the byte range is flushed.
  1101.  *
  1102.  * ----------------------------------------------------------------------------
  1103.  */
  1104. .globl    _VmMach_FlushByteRange
  1105. _VmMach_FlushByteRange:
  1106.     /* Start prologue */
  1107.     save    %sp, (-MACH_SAVED_WINDOW_SIZE), %sp
  1108.     /* end prologue */
  1109.  
  1110.     /* Address of last byte to flush */
  1111.     add        %i0, %i1, %OUT_TEMP2
  1112.     sub        %OUT_TEMP2, 1, %OUT_TEMP2
  1113.  
  1114.     /* Get first line to flush */
  1115. #ifdef sun4c
  1116.     sethi    %hi(_vmCacheLineSize), %l0
  1117.     ld        [%l0 + %lo(_vmCacheLineSize)], %l0
  1118.     sub        %g0, %l0, %OUT_TEMP1
  1119. #else
  1120.     set        ~(VMMACH_CACHE_LINE_SIZE - 1), %OUT_TEMP1
  1121. #endif
  1122.     and        %i0, %OUT_TEMP1, %i0
  1123.  
  1124.     /* Get last line to flush */
  1125.     and        %OUT_TEMP2, %OUT_TEMP1, %VOL_TEMP1
  1126.  
  1127.     /* Get number of lines to flush */
  1128.     sub        %VOL_TEMP1, %i0, %OUT_TEMP2
  1129. #ifdef sun4c
  1130.     sethi    %hi(_vmCacheShift), %VOL_TEMP2
  1131.     ld        [%VOL_TEMP2 + %lo(_vmCacheShift)], %VOL_TEMP2
  1132.     srl        %OUT_TEMP2, %VOL_TEMP2, %OUT_TEMP2
  1133. #else
  1134.     srl        %OUT_TEMP2, VMMACH_CACHE_SHIFT, %OUT_TEMP2
  1135. #endif
  1136.     add        %OUT_TEMP2, 1, %i3
  1137.  
  1138. #ifndef sun4c
  1139.     set        VMMACH_CACHE_LINE_SIZE, %l0
  1140. #endif
  1141.     sll        %l0, 4, %i5        /* VMMACH_CACHE_LINE_SIZE * 16 */
  1142.  
  1143.     /* Do we have at least 16 lines to flush? */
  1144.     subcc    %i3, 16, %g0
  1145.     bl        FinishFlushing
  1146.     nop
  1147.  
  1148.     add        %l0, %l0, %l1
  1149.     add        %l1, %l0, %l2
  1150.     add        %l2, %l0, %l3
  1151.     add        %l3, %l0, %l4
  1152.     add        %l4, %l0, %l5
  1153.     add        %l5, %l0, %l6
  1154.     add        %l6, %l0, %l7
  1155.     add        %l7, %l0, %o0
  1156.     add        %o0, %l0, %o1
  1157.     add        %o1, %l0, %o2
  1158.     add        %o2, %l0, %o3
  1159.     add        %o3, %l0, %o4
  1160.     add        %o4, %l0, %o5
  1161.     add        %o5, %l0, %i4
  1162.  
  1163. FlushingHere:
  1164.     /* We have at least 16 lines to flush. */
  1165.     sub        %i3, 16, %i3
  1166.  
  1167.     /* Try to space them out to avoid back-to-back copies. */
  1168.  
  1169.     /*
  1170.      * Is this far enough spaced??  How many lines on average will the routine
  1171.      * be asked to flush?
  1172.      */
  1173.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1174.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_PAGE_SPACE
  1175.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_PAGE_SPACE
  1176.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_PAGE_SPACE
  1177.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_PAGE_SPACE
  1178.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_PAGE_SPACE
  1179.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_PAGE_SPACE
  1180.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_PAGE_SPACE
  1181.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_PAGE_SPACE
  1182.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_PAGE_SPACE
  1183.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_PAGE_SPACE
  1184.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_PAGE_SPACE
  1185.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_PAGE_SPACE
  1186.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_PAGE_SPACE
  1187.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_PAGE_SPACE
  1188.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_PAGE_SPACE
  1189.  
  1190.     /* Are there another 16 lines? */
  1191.     subcc       %i3, 16, %g0
  1192.     bge        FlushingHere
  1193.     add        %i0, %i5, %i0                    /* delay slot */
  1194.     tst        %i3
  1195.     be        DoneFlushing    /* We finished with the last 16 lines... */
  1196.     nop
  1197. FinishFlushing:
  1198.     /* Finish the rest line by line.  Should I optimize here?  How much? */
  1199.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1200.     subcc    %i3, 1, %i3
  1201.     bg        FinishFlushing
  1202.     add        %i0, %l0, %i0                    /* delay slot */
  1203.  
  1204. DoneFlushing:
  1205.     ret
  1206.     restore
  1207.  
  1208. /*
  1209.  * ----------------------------------------------------------------------------
  1210.  *
  1211.  * VmMachFlushPage --
  1212.  *
  1213.  *         Flush a page from the cache.
  1214.  *
  1215.  *    void VmMachFlushPage(pageVirtAddr)
  1216.  *    Address    pageVirtAddr;    (Address of page)
  1217.  *
  1218.  * Results:
  1219.  *     None.
  1220.  *
  1221.  * Side effects:
  1222.  *     All data cached from the page is flushed from the cache.
  1223.  *
  1224.  * ----------------------------------------------------------------------------
  1225.  */
  1226. .globl    _VmMachFlushPage
  1227. _VmMachFlushPage:
  1228.     /* Start prologue */
  1229.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  1230.     save    %sp, %OUT_TEMP1, %sp
  1231.     /* end prologue */
  1232.     
  1233.     set        ~VMMACH_OFFSET_MASK_INT, %o0
  1234.     and        %i0, %o0, %i0            /* beginning of page */
  1235.  
  1236.     sethi    %hi(_vmMachHasHwFlush), %OUT_TEMP1
  1237.     ld        [%OUT_TEMP1 + %lo(_vmMachHasHwFlush)], %OUT_TEMP1
  1238.     tst        %OUT_TEMP1
  1239.     be        SoftFlushPage
  1240.     nop
  1241.     /*
  1242.      * 4/75 has a hardware page at a time flush that can clear a
  1243.      * segment
  1244.      */
  1245.     sta        %g0, [%i0] VMMACH_HWFLUSH_PAGE_SPACE
  1246.  
  1247.     ret
  1248.     restore
  1249.  
  1250. SoftFlushPage:
  1251.  
  1252.                             /* number of loops */
  1253. #ifdef sun4c
  1254.     sethi    %hi(_vmCacheShift), %OUT_TEMP1
  1255.     ld        [%OUT_TEMP1 + %lo(_vmCacheShift)], %OUT_TEMP1
  1256.     set        VMMACH_PAGE_SIZE_INT, %i1
  1257.     srl        %i1, %OUT_TEMP1, %i1
  1258.     srl        %i1, 4, %i1
  1259. #else
  1260.     set        (VMMACH_PAGE_SIZE_INT / VMMACH_CACHE_LINE_SIZE / 16), %i1
  1261. #endif
  1262.  
  1263.     /*
  1264.      * Spread the stores evenly through 16 chunks of the page flush area in the
  1265.      * cache.  This helps to avoid back-to-back writebacks.
  1266.      */
  1267.     set        (VMMACH_PAGE_SIZE_INT / 16), %l0
  1268.  
  1269.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  1270.     add        %i0, %l0, %i0
  1271. #ifdef sun4c
  1272.     sethi    %hi(_vmCacheLineSize), %i5
  1273.     ld        [%i5 + %lo(_vmCacheLineSize)], %i5
  1274. #else
  1275.     set        VMMACH_CACHE_LINE_SIZE, %i5
  1276. #endif
  1277.     sub        %i0, %i5, %i0
  1278.  
  1279.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  1280.     add        %l0, (VMMACH_PAGE_SIZE_INT / 16), %l1
  1281.     add        %l1, (VMMACH_PAGE_SIZE_INT / 16), %l2
  1282.     add        %l2, (VMMACH_PAGE_SIZE_INT / 16), %l3
  1283.     add        %l3, (VMMACH_PAGE_SIZE_INT / 16), %l4
  1284.     add        %l4, (VMMACH_PAGE_SIZE_INT / 16), %l5
  1285.     add        %l5, (VMMACH_PAGE_SIZE_INT / 16), %l6
  1286.     add        %l6, (VMMACH_PAGE_SIZE_INT / 16), %l7
  1287.  
  1288.     add        %l7, (VMMACH_PAGE_SIZE_INT / 16), %o0
  1289.     add        %o0, (VMMACH_PAGE_SIZE_INT / 16), %o1
  1290.     add        %o1, (VMMACH_PAGE_SIZE_INT / 16), %o2
  1291.     add        %o2, (VMMACH_PAGE_SIZE_INT / 16), %o3
  1292.     add        %o3, (VMMACH_PAGE_SIZE_INT / 16), %o4
  1293.     add        %o4, (VMMACH_PAGE_SIZE_INT / 16), %o5
  1294.     add        %o5, (VMMACH_PAGE_SIZE_INT / 16), %i4
  1295.  
  1296. FlushingPage:
  1297.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1298.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_PAGE_SPACE
  1299.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_PAGE_SPACE
  1300.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_PAGE_SPACE
  1301.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_PAGE_SPACE
  1302.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_PAGE_SPACE
  1303.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_PAGE_SPACE
  1304.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_PAGE_SPACE
  1305.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_PAGE_SPACE
  1306.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_PAGE_SPACE
  1307.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_PAGE_SPACE
  1308.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_PAGE_SPACE
  1309.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_PAGE_SPACE
  1310.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_PAGE_SPACE
  1311.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_PAGE_SPACE
  1312.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_PAGE_SPACE
  1313.  
  1314.     subcc    %i1, 1, %i1                /* decrement loop */
  1315.     bne        FlushingPage
  1316.     sub        %i0, %i5, %i0                /* delay slot */
  1317.     ret
  1318.     restore
  1319. #ifndef sun4c
  1320. /*
  1321.  * ----------------------------------------------------------------------------
  1322.  *
  1323.  * VmMachSetup32BitDVMA --
  1324.  *
  1325.  *      Return the user DVMA to access the lower 256 megabytes of context 0.
  1326.  *    We use this space to map pages for DMA.
  1327.  *
  1328.  *
  1329.  * Results:
  1330.  *     None.
  1331.  *
  1332.  * Side effects:
  1333.  *     None.
  1334.  *
  1335.  * ----------------------------------------------------------------------------
  1336.  */
  1337.  
  1338. .globl  _VmMachSetup32BitDVMA
  1339. _VmMachSetup32BitDVMA:
  1340.     /*
  1341.      * First we initialized the map for VME context 0 to map into the
  1342.      * lower 256 megabytes of the context 0. The DVMA map takes the form
  1343.      * of an eight element array index by bits 30 to 28 from the VME bus. 
  1344.      *  each entry looking like:
  1345.      *   struct 32BitDVMAMap {
  1346.      *        unsigned char  :4;
  1347.      *        unsigned char  topNibble:4;   Top four bits of DMA address. 
  1348.      *        unsigned char  context:8;     Context to access. 
  1349.      * }
  1350.      *        
  1351.      * We initialized the following mapping:
  1352.      * VME 32 addresses 0x80000000 - 0x8fffffff to 0 - 0x0fffffff of context 0.
  1353.      */
  1354.     set         VMMACH_USER_DVMA_MAP, %OUT_TEMP1
  1355.     stba        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1356.     add        %OUT_TEMP1,1,%OUT_TEMP1
  1357.     stba        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1358.  
  1359.     /*
  1360.      * Enable user DVMA from VME context 0 (ie 0x80000000 - 0x8fffffff)
  1361.      * The User DVMA enable register takes the form of a bitmap will one
  1362.      * bit per VME context.
  1363.      */
  1364.     set         VMMACH_USER_DVMA_ENABLE_REG, %OUT_TEMP1
  1365.     mov        1, %OUT_TEMP2
  1366.     stba        %OUT_TEMP2, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1367.  
  1368.     retl                /* Return from leaf routine */
  1369.     nop
  1370.  
  1371. #endif
  1372. /*
  1373.  * ----------------------------------------------------------------------
  1374.  *
  1375.  * VmMachQuickNDirtyCopy --
  1376.  *
  1377.  *    Copy numBytes from *sourcePtr in to *destPtr, with accesses to sourcePtr
  1378.  *    in sourceContext and accesses to destPtr in destContext.
  1379.  *    This routine is optimized to do transfers when sourcePtr and 
  1380.  *    destPtr are both double-word aligned.
  1381.  *
  1382.  *    ReturnStatus
  1383.  *    VmMachQuickNDirtyCopy(numBytes, sourcePtr, destPtr, sourceContext,
  1384.  *                                destContext)
  1385.  *        register int numBytes;      The number of bytes to copy
  1386.  *        Address sourcePtr;          Where to copy from.
  1387.  *        Address destPtr;            Where to copy to.
  1388.  *        unsigned int sourceContext;    Context to access source in.
  1389.  *        unsigned int destContext;    Context to access dest in.
  1390.  *
  1391.  * Results:
  1392.  *    Returns SUCCESS if the copy went OK (which should be often).  If
  1393.  *    a bus error (INCLUDING a page fault) occurred while reading or
  1394.  *    writing user memory, then FAILURE is returned (this return
  1395.  *    occurs from the trap handler, rather than from this procedure).
  1396.  *
  1397.  * Side effects:
  1398.  *    The area that destPtr points to is modified.
  1399.  *
  1400.  * ----------------------------------------------------------------------
  1401.  */
  1402. .globl _VmMachQuickNDirtyCopy
  1403. _VmMachQuickNDirtyCopy:
  1404.     /* Start prologue */
  1405.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP2
  1406.     save    %sp, %OUT_TEMP2, %sp
  1407.     /* end prologue */
  1408.                         /* numBytes in i0 */
  1409.                         /* sourcePtr in i1 */
  1410.                         /* destPtr in i2 */
  1411.                         /* sourceContext in i3 */
  1412.                         /* destContext in i4 */
  1413.  
  1414.     /* use %i5 for context reg offset */
  1415.     set        VMMACH_CONTEXT_OFF, %i5
  1416.  
  1417. /*
  1418.  * If the source or dest are not double-word aligned then everything must be
  1419.  * done as word or byte copies.
  1420.  */
  1421.     or        %i1, %i2, %OUT_TEMP1
  1422.     andcc    %OUT_TEMP1, 7, %g0
  1423.     be        QDoubleWordCopy
  1424.     nop
  1425.     andcc    %OUT_TEMP1, 3, %g0
  1426.     be        QWordCopy
  1427.     nop
  1428.     ba        QByteCopyIt
  1429.     nop
  1430.  
  1431.     /*
  1432.      * Do as many 64-byte copies as possible.
  1433.      */
  1434.  
  1435. QDoubleWordCopy:
  1436.     cmp        %i0, 64
  1437.     bl         QFinishWord
  1438.     nop
  1439.  
  1440.     /* set context to sourceContext */
  1441.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1442.  
  1443.     ldd        [%i1], %l0
  1444.     ldd        [%i1 + 8], %l2
  1445.     ldd        [%i1 + 16], %l4
  1446.     ldd        [%i1 + 24], %l6
  1447.     ldd        [%i1 + 32], %o0
  1448.     ldd        [%i1 + 40], %o2
  1449.     ldd        [%i1 + 48], %o4
  1450.     ldd        [%i1 + 56], %g6
  1451.     
  1452.     /* set context to destContext */
  1453.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1454.  
  1455.     std        %l0, [%i2]
  1456.     std        %l2, [%i2 + 8]
  1457.     std        %l4, [%i2 + 16]
  1458.     std        %l6, [%i2 + 24]
  1459.     std        %o0, [%i2 + 32]
  1460.     std        %o2, [%i2 + 40]
  1461.     std        %o4, [%i2 + 48]
  1462.     std        %g6, [%i2 + 56]
  1463.  
  1464.     sub       %i0, 64, %i0
  1465.     add        %i1, 64, %i1
  1466.     add        %i2, 64, %i2
  1467.     ba         QDoubleWordCopy
  1468.     nop
  1469. QWordCopy:
  1470.     cmp        %i0, 64
  1471.     bl        QFinishWord
  1472.     nop
  1473.  
  1474.     /* from context */
  1475.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1476.  
  1477.     ld        [%i1], %l0
  1478.     ld        [%i1 + 4], %l1
  1479.     ld        [%i1 + 8], %l2
  1480.     ld        [%i1 + 12], %l3
  1481.     ld        [%i1 + 16], %l4
  1482.     ld        [%i1 + 20], %l5
  1483.     ld        [%i1 + 24], %l6
  1484.     ld        [%i1 + 28], %l7
  1485.  
  1486.     /* to context */
  1487.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1488.  
  1489.     st        %l0, [%i2]
  1490.     st        %l1, [%i2 + 4]
  1491.     st        %l2, [%i2 + 8]
  1492.     st        %l3, [%i2 + 12]
  1493.     st        %l4, [%i2 + 16]
  1494.     st        %l5, [%i2 + 20]
  1495.     st        %l6, [%i2 + 24]
  1496.     st        %l7, [%i2 + 28]
  1497.  
  1498.     /* from context */
  1499.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1500.  
  1501.     ld        [%i1 + 32], %l0
  1502.     ld        [%i1 + 36], %l1
  1503.     ld        [%i1 + 40], %l2
  1504.     ld        [%i1 + 44], %l3
  1505.     ld        [%i1 + 48], %l4
  1506.     ld        [%i1 + 52], %l5
  1507.     ld        [%i1 + 56], %l6
  1508.     ld        [%i1 + 60], %l7
  1509.     
  1510.     /* to context */
  1511.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1512.  
  1513.     st        %l0, [%i2 + 32]
  1514.     st        %l1, [%i2 + 36]
  1515.     st        %l2, [%i2 + 40]
  1516.     st        %l3, [%i2 + 44]
  1517.     st        %l4, [%i2 + 48]
  1518.     st        %l5, [%i2 + 52]
  1519.     st        %l6, [%i2 + 56]
  1520.     st        %l7, [%i2 + 60]
  1521.  
  1522.     sub       %i0, 64, %i0
  1523.     add        %i1, 64, %i1
  1524.     add        %i2, 64, %i2
  1525.     ba         QWordCopy
  1526.     nop
  1527.  
  1528.     /*
  1529.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  1530.      * quickly by dispatching into the middle of a sequence of move
  1531.      * instructions, but I don't yet.
  1532.      */
  1533.  
  1534. QFinishWord:
  1535.     cmp        %i0, 4
  1536.     bl        QByteCopyIt
  1537.     nop
  1538.     /* from context */
  1539.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1540.  
  1541.     ld        [%i1], %l0
  1542.  
  1543.     /* to context */
  1544.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1545.  
  1546.     st        %l0, [%i2]
  1547.     sub        %i0, 4, %i0
  1548.     add        %i1, 4, %i1
  1549.     add        %i2, 4, %i2
  1550.     ba        QFinishWord
  1551.     nop
  1552.     
  1553.     /*
  1554.      * Do one byte copies until done.
  1555.      */
  1556. QByteCopyIt:
  1557.     tst        %i0
  1558.     ble         QDoneCopying
  1559.     nop
  1560.  
  1561.     /* from context */
  1562.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1563.  
  1564.     ldub    [%i1], %l0
  1565.  
  1566.     /* to context */
  1567.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1568.  
  1569.     stb        %l0, [%i2]
  1570.     sub        %i0, 1, %i0
  1571.     add        %i1, 1, %i1
  1572.     add        %i2, 1, %i2
  1573.     ba         QByteCopyIt
  1574.     nop
  1575.  
  1576.     /* 
  1577.      * Return.
  1578.      */
  1579.  
  1580. QDoneCopying: 
  1581.     clr        %i0    /* SUCCESS */
  1582.     ret
  1583.     restore
  1584.  
  1585. .globl _VmMachEndQuickCopy
  1586. _VmMachEndQuickCopy:
  1587.  
  1588.  
  1589.  
  1590. /*
  1591.  * ----------------------------------------------------------------------
  1592.  *
  1593.  * Vm_Copy{In,Out}
  1594.  *
  1595.  *    Copy numBytes from *sourcePtr in to *destPtr.
  1596.  *    This routine is optimized to do transfers when sourcePtr and 
  1597.  *    destPtr are both double-word aligned.
  1598.  *
  1599.  *    ReturnStatus
  1600.  *    Vm_Copy{In,Out}(numBytes, sourcePtr, destPtr)
  1601.  *        register int numBytes;      The number of bytes to copy
  1602.  *        Address sourcePtr;          Where to copy from.
  1603.  *        Address destPtr;            Where to copy to.
  1604.  *
  1605.  * Results:
  1606.  *    Returns SUCCESS if the copy went OK (which is almost always).  If
  1607.  *    a bus error (other than a page fault) occurred while reading or
  1608.  *    writing user memory, then SYS_ARG_NO_ACCESS is returned (this return
  1609.  *    occurs from the trap handler, rather than from this procedure).
  1610.  *
  1611.  * Side effects:
  1612.  *    The area that destPtr points to is modified.
  1613.  *
  1614.  * ----------------------------------------------------------------------
  1615.  */
  1616. .globl _VmMachDoCopy
  1617. .globl _Vm_CopyIn
  1618. _VmMachDoCopy:
  1619. _Vm_CopyIn:
  1620.                         /* numBytes in o0 */
  1621.                         /* sourcePtr in o1 */
  1622.                         /* destPtr in o2 */
  1623. /*
  1624.  * If the source or dest are not double-word aligned then everything must be
  1625.  * done as word or byte copies.
  1626.  */
  1627.  
  1628. GotArgs:
  1629.     or        %o1, %o2, %OUT_TEMP1
  1630.     andcc    %OUT_TEMP1, 7, %g0
  1631.     be        DoubleWordCopy
  1632.     nop
  1633.     andcc    %OUT_TEMP1, 3, %g0
  1634.     be        WordCopy
  1635.     nop
  1636.     ba        ByteCopyIt
  1637.     nop
  1638.  
  1639.     /*
  1640.      * Do as many 64-byte copies as possible.
  1641.      */
  1642.  
  1643. DoubleWordCopy:
  1644.     cmp        %o0, 64
  1645.     bl         FinishWord
  1646.     nop
  1647.     ldd        [%o1], %OUT_TEMP1    /* uses out_temp1 and out_temp2 */
  1648.     std        %OUT_TEMP1, [%o2]
  1649.     ldd        [%o1 + 8], %OUT_TEMP1
  1650.     std        %OUT_TEMP1, [%o2 + 8]
  1651.     ldd        [%o1 + 16], %OUT_TEMP1
  1652.     std        %OUT_TEMP1, [%o2 + 16]
  1653.     ldd        [%o1 + 24], %OUT_TEMP1
  1654.     std        %OUT_TEMP1, [%o2 + 24]
  1655.     ldd        [%o1 + 32], %OUT_TEMP1
  1656.     std        %OUT_TEMP1, [%o2 + 32]
  1657.     ldd        [%o1 + 40], %OUT_TEMP1
  1658.     std        %OUT_TEMP1, [%o2 + 40]
  1659.     ldd        [%o1 + 48], %OUT_TEMP1
  1660.     std        %OUT_TEMP1, [%o2 + 48]
  1661.     ldd        [%o1 + 56], %OUT_TEMP1
  1662.     std        %OUT_TEMP1, [%o2 + 56]
  1663.     
  1664.     sub       %o0, 64, %o0
  1665.     add        %o1, 64, %o1
  1666.     add        %o2, 64, %o2
  1667.     ba         DoubleWordCopy
  1668.     nop
  1669. WordCopy:
  1670.     cmp        %o0, 64
  1671.     bl        FinishWord
  1672.     nop
  1673.     ld        [%o1], %OUT_TEMP1
  1674.     st        %OUT_TEMP1, [%o2]
  1675.     ld        [%o1 + 4], %OUT_TEMP1
  1676.     st        %OUT_TEMP1, [%o2 + 4]
  1677.     ld        [%o1 + 8], %OUT_TEMP1
  1678.     st        %OUT_TEMP1, [%o2 + 8]
  1679.     ld        [%o1 + 12], %OUT_TEMP1
  1680.     st        %OUT_TEMP1, [%o2 + 12]
  1681.     ld        [%o1 + 16], %OUT_TEMP1
  1682.     st        %OUT_TEMP1, [%o2 + 16]
  1683.     ld        [%o1 + 20], %OUT_TEMP1
  1684.     st        %OUT_TEMP1, [%o2 + 20]
  1685.     ld        [%o1 + 24], %OUT_TEMP1
  1686.     st        %OUT_TEMP1, [%o2 + 24]
  1687.     ld        [%o1 + 28], %OUT_TEMP1
  1688.     st        %OUT_TEMP1, [%o2 + 28]
  1689.     ld        [%o1 + 32], %OUT_TEMP1
  1690.     st        %OUT_TEMP1, [%o2 + 32]
  1691.     ld        [%o1 + 36], %OUT_TEMP1
  1692.     st        %OUT_TEMP1, [%o2 + 36]
  1693.     ld        [%o1 + 40], %OUT_TEMP1
  1694.     st        %OUT_TEMP1, [%o2 + 40]
  1695.     ld        [%o1 + 44], %OUT_TEMP1
  1696.     st        %OUT_TEMP1, [%o2 + 44]
  1697.     ld        [%o1 + 48], %OUT_TEMP1
  1698.     st        %OUT_TEMP1, [%o2 + 48]
  1699.     ld        [%o1 + 52], %OUT_TEMP1
  1700.     st        %OUT_TEMP1, [%o2 + 52]
  1701.     ld        [%o1 + 56], %OUT_TEMP1
  1702.     st        %OUT_TEMP1, [%o2 + 56]
  1703.     ld        [%o1 + 60], %OUT_TEMP1
  1704.     st        %OUT_TEMP1, [%o2 + 60]
  1705.     
  1706.     sub       %o0, 64, %o0
  1707.     add        %o1, 64, %o1
  1708.     add        %o2, 64, %o2
  1709.     ba         WordCopy
  1710.     nop
  1711.  
  1712.     /*
  1713.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  1714.      * quickly by dispatching into the middle of a sequence of move
  1715.      * instructions, but I don't yet.
  1716.      */
  1717.  
  1718. FinishWord:
  1719.     cmp        %o0, 4
  1720.     bl        ByteCopyIt
  1721.     nop
  1722.     ld        [%o1], %OUT_TEMP1
  1723.     st        %OUT_TEMP1, [%o2]
  1724.     sub        %o0, 4, %o0
  1725.     add        %o1, 4, %o1
  1726.     add        %o2, 4, %o2
  1727.     ba        FinishWord
  1728.     nop
  1729.     
  1730.     /*
  1731.      * Do one byte copies until done.
  1732.      */
  1733. ByteCopyIt:
  1734.     tst        %o0
  1735.     ble         DoneCopying
  1736.     nop
  1737.     ldub    [%o1], %OUT_TEMP1
  1738.     stb        %OUT_TEMP1, [%o2]
  1739.     sub        %o0, 1, %o0
  1740.     add        %o1, 1, %o1
  1741.     add        %o2, 1, %o2
  1742.     ba         ByteCopyIt
  1743.     nop
  1744.  
  1745.     /* 
  1746.      * Return.
  1747.      */
  1748.  
  1749. DoneCopying: 
  1750.     clr        %o0
  1751.     retl        /* return from leaf routine */
  1752.     nop
  1753.  
  1754. /*
  1755.  * Vm_CopyOut is just like Vm_CopyIn except that it checks to make sure
  1756.  * that the destination is in the user area (otherwise this would be a
  1757.  * trap door to write to kernel space).
  1758.  */
  1759.  
  1760. .globl _Vm_CopyOut, _mach_FirstUserAddr, _mach_LastUserAddr
  1761. _Vm_CopyOut:
  1762.                         /* numBytes in o0 */
  1763.                         /* sourcePtr in o1 */
  1764.                         /* destPtr in o2 */
  1765.     sethi    %hi(_mach_FirstUserAddr), %OUT_TEMP1
  1766.                         /* get 1st user addr */
  1767.     ld        [%OUT_TEMP1 + %lo(_mach_FirstUserAddr)], %OUT_TEMP1
  1768.     cmp        %o2, %OUT_TEMP1
  1769.     blu        BadAddress        /* branch carry set */
  1770.     nop
  1771.     sub        %o2, 1, %OUT_TEMP2
  1772.     addcc    %OUT_TEMP2, %o0, %OUT_TEMP2
  1773.     blu        BadAddress
  1774.     nop
  1775.  
  1776.     sethi    %hi(_mach_LastUserAddr), %OUT_TEMP1
  1777.     ld        [%OUT_TEMP1 + %lo(_mach_LastUserAddr)], %OUT_TEMP1
  1778.     cmp        %OUT_TEMP2, %OUT_TEMP1
  1779.     bleu    GotArgs
  1780.     nop
  1781.  
  1782.     /*
  1783.      * User address out of range.  Check for a zero byte count before
  1784.      * returning an error, though;  there appear to be kernel routines
  1785.      * that call Vm_CopyOut with a zero count but bogus other arguments.
  1786.      */
  1787.  
  1788. BadAddress:
  1789.     tst        %o0
  1790.     bne        BadAddressTruly
  1791.     clr        %RETURN_VAL_REG
  1792.     retl
  1793.     nop
  1794. BadAddressTruly:
  1795.     set        SYS_ARG_NOACCESS, %RETURN_VAL_REG
  1796.     retl
  1797.     nop
  1798.  
  1799. /*
  1800.  * ----------------------------------------------------------------------
  1801.  *
  1802.  * Vm_StringNCopy
  1803.  *
  1804.  *    Copy the NULL terminated string from *sourcePtr to *destPtr up
  1805.  *    numBytes worth of bytes.
  1806.  *
  1807.  *    void
  1808.  *    Vm_StringNCopy(numBytes, sourcePtr, destPtr, bytesCopiedPtr)
  1809.  *        register int numBytes;      The number of bytes to copy
  1810.  *        Address sourcePtr;          Where to copy from.
  1811.  *        Address destPtr;            Where to copy to.
  1812.  *        int    *bytesCopiedPtr;    Number of bytes copied.
  1813.  *
  1814.  *    NOTE: The trap handler assumes that this routine does not push anything
  1815.  *          onto the stack.  It uses this fact to allow it to return to the
  1816.  *          caller of this routine upon an address fault.  If you must push
  1817.  *          something onto the stack then you had better go and modify 
  1818.  *          "CallTrapHandler" in asmDefs.h appropriately.
  1819.  *
  1820.  * Results:
  1821.  *    Normally returns SUCCESS.  If a non-recoverable bus error occurs,
  1822.  *    then the trap handler fakes up a SYS_ARG_NO_ACCESS return from
  1823.  *    this procedure.
  1824.  *
  1825.  * Side effects:
  1826.  *    The area that destPtr points to is modified and *bytesCopiedPtr 
  1827.  *    contains the number of bytes copied.  NOTE: this always copies
  1828.  *    at least one char, even if the numBytes param is zero!!!
  1829.  *
  1830.  * ----------------------------------------------------------------------
  1831.  */
  1832. .globl  _Vm_StringNCopy
  1833. _Vm_StringNCopy:
  1834.                         /* numBytes in o0 */
  1835.                         /* sourcePtr in o1 */
  1836.                         /* destPtr in o2 */
  1837.                         /* bytesCopiedPtr in o3 */
  1838.  
  1839.     mov        %o0, %OUT_TEMP2            /* save numBytes */
  1840. StartCopyingChars: 
  1841.     ldub    [%o1], %OUT_TEMP1        /* Copy the character */
  1842.     stb        %OUT_TEMP1, [%o2]
  1843.     add        %o1, 1, %o1            /* increment addresses */
  1844.     add        %o2, 1, %o2
  1845.     cmp        %OUT_TEMP1, 0            /* See if hit null in string. */
  1846.     be        NullChar
  1847.     nop
  1848.  
  1849.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2    /* Decrement the byte counter */
  1850.     bne        StartCopyingChars        /* Copy more chars if haven't */
  1851.     nop                     /*     reached the limit. */
  1852. NullChar: 
  1853.     sub        %o0, %OUT_TEMP2, %OUT_TEMP2    /* Compute # of bytes copied */
  1854.     st        %OUT_TEMP2, [%o3]         /* and store the result. */
  1855.     clr     %RETURN_VAL_REG            /* Return SUCCESS. */
  1856.     retl
  1857.     nop
  1858.  
  1859.  
  1860. /*
  1861.  * ----------------------------------------------------------------------
  1862.  *
  1863.  * VmMachTouchPages --
  1864.  *
  1865.  *    Touch the range of pages.
  1866.  *
  1867.  *    ReturnStatus
  1868.  *    VmMachTouchPages(firstPage, numPages)
  1869.  *        int    firstPage;    First page to touch.
  1870.  *        int    numPages;    Number of pages to touch.
  1871.  *
  1872.  *    NOTE: The trap handler assumes that this routine does not push anything
  1873.  *          onto the stack.  It uses this fact to allow it to return to the
  1874.  *          caller of this routine upon an address fault.  If you must push
  1875.  *          something onto the stack then you had better go and modify 
  1876.  *          "CallTrapHandler" in asmDefs.h appropriately.
  1877.  *
  1878.  * Results:
  1879.  *    Returns SUCCESS if we're able to touch the page (which is almost
  1880.  *    always).  If a bus error (other than a page fault) occurred while 
  1881.  *    reading user memory, then SYS_ARG_NO_ACCESS is returned (this return
  1882.  *    occurs from the trap handler, rather than from this procedure).
  1883.  *
  1884.  * Side effects:
  1885.  *    None.
  1886.  *
  1887.  * ----------------------------------------------------------------------
  1888.  */
  1889. .globl _VmMachTouchPages
  1890. _VmMachTouchPages:
  1891.                 /* o0 = first page = starting addr */
  1892.                 /* o1 = numPages */
  1893.     set        VMMACH_PAGE_SHIFT_INT, %OUT_TEMP1
  1894.     sll        %o0, %OUT_TEMP1, %o0    /* o0 = o0 << VMMACH_PAGE_SHIFT_INT */
  1895.     /* Mike had arithmetic shift here, why??? */
  1896. StartTouchingPages:
  1897.     tst        %o1        /* Quit when %o1 == 0 */
  1898.     be        DoneTouchingPages
  1899.     nop
  1900.     ld        [%o0], %OUT_TEMP1    /* Touch page at addr in %o0 */
  1901.     sub        %o1, 1, %o1    /* Go back around to touch the next page. */
  1902.     set        VMMACH_PAGE_SIZE_INT, %OUT_TEMP2
  1903.     add        %o0, %OUT_TEMP2, %o0
  1904.     ba        StartTouchingPages
  1905.     nop
  1906.  
  1907. DoneTouchingPages:
  1908.     clr        %RETURN_VAL_REG        /* return success */
  1909.     retl
  1910.     nop
  1911.  
  1912. /*
  1913.  * The address marker below is there so that the trap handler knows the
  1914.  * end of code that may take a page fault while copying into/out of
  1915.  * user space.
  1916.  */
  1917.  
  1918. .globl    _VmMachCopyEnd
  1919. _VmMachCopyEnd:
  1920.